﻿using Microsoft.Graphics.Canvas;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Numerics;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using 纸片人.AttributeUsageFloder;
using 纸片人.CalculateControls;
using 纸片人.InterfaceFolder;
using 纸片人.win2dEffectControl;
using 纸片人.win2dEffectControl.DataClass;


// https://go.microsoft.com/fwlink/?LinkId=234238 上介绍了“空白页”项模板

namespace 纸片人.PageViews
{
    [LastModified("2022-5-12","AddToMainWindow")]
    [PageTypeAttribute("gpu","Win2DGraph")]
    /// <summary>
    /// 可用于自身或导航至 Frame 内部的空白页。
    /// </summary>
    public sealed partial class WindConnectLinePage : Page
    {
        /// <summary>
        /// 当前最大的深度值
        /// </summary>
        private int zIndex = 0;
        /// <summary>
        /// 当前选中的效果空间
        /// </summary>
        EffectContentControl selectEffectContentControl;

        List<ConnectLine> listConnectLines = new List<ConnectLine>();

        List<EffectControlType> listEffectControlTypes = new List<EffectControlType>();
        List<EffectControlType> listCalute = new List<EffectControlType>();
        public WindConnectLinePage()
        {
            this.InitializeComponent();

            listEffectControlTypes.Add(new EffectControlType(typeof(CanvasBitmapControl)));
            listEffectControlTypes.Add(new EffectControlType(typeof(TurbulenceEffectControl)));
            listEffectControlTypes.Add(new EffectControlType(typeof(OpacityEffectControl)));
            listEffectControlTypes.Add(new EffectControlType(typeof(DisplacementMapEffectControl)));
            listEffectControlTypes.Add(new EffectControlType(typeof(GrayscaleEffectControl)));
            listEffectControlTypes.Add(new EffectControlType(typeof(MorphologyEffectControl)));
            listEffectControlTypes.Add(new EffectControlType(typeof(BorderEffectControl)));
            listEffectControlTypes.Add(new EffectControlType(typeof(GaussianBlurEffectControl)));
            listEffectControlTypes.Add(new EffectControlType(typeof(Transform2DEffectControl)));
            listEffectControlTypes.Add(new EffectControlType(typeof(AlphaMaskEffectControl)));
            listEffectControlTypes.Add(new EffectControlType(typeof(ArithmeticCompositeEffectControl)));
            //listEffectControlTypes.Add(new EffectControlType(typeof(AtlasEffectControl)));
            listEffectControlTypes.Add(new EffectControlType(typeof(BlendEffectControl)));
            listEffectControlTypes.Add(new EffectControlType(typeof(BrightnessEffectControl)));
            listEffectControlTypes.Add(new EffectControlType(typeof(ChromaKeyEffectControl)));
            listEffectControlTypes.Add(new EffectControlType(typeof(ContrastEffectControl)));
            listEffectControlTypes.Add(new EffectControlType(typeof(CropEffectControl)));
            listEffectControlTypes.Add(new EffectControlType(typeof(CrossFadeEffectControl)));
            listEffectControlTypes.Add(new EffectControlType(typeof(DirectionalBlurEffectControl)));
            listEffectControlTypes.Add(new EffectControlType(typeof(EdgeDetectionEffectControl)));
            listEffectControlTypes.Add(new EffectControlType(typeof(EmbossEffectControl)));
            listEffectControlTypes.Add(new EffectControlType(typeof(ExposureEffectControl)));
            listEffectControlTypes.Add(new EffectControlType(typeof(HighlightsAndShadowsEffectControl)));
            listEffectControlTypes.Add(new EffectControlType(typeof(HueRotationEffectControl)));
            listEffectControlTypes.Add(new EffectControlType(typeof(HueToRgbEffectControl)));

            listEffectControlTypes.Add(new EffectControlType(typeof(InvertEffectControl)));
            listEffectControlTypes.Add(new EffectControlType(typeof(LuminanceToAlphaEffectControl)));
            listEffectControlTypes.Add(new EffectControlType(typeof(OpacityMetadateEffectControl)));
            listEffectControlTypes.Add(new EffectControlType(typeof(VignetteEffectControl)));
            listEffectControlTypes.Add(new EffectControlType(typeof(UnPremultiplyEffectControl)));
            listEffectControlTypes.Add(new EffectControlType(typeof(TintEffectControl)));
            listEffectControlTypes.Add(new EffectControlType(typeof(TileEffectControl)));
            listEffectControlTypes.Add(new EffectControlType(typeof(StraightenEffectControl)));
            listEffectControlTypes.Add(new EffectControlType(typeof(TemperatureAndTintEffectControl)));
            listEffectControlTypes.Add(new EffectControlType(typeof(SharpenEffectControl)));
            listEffectControlTypes.Add(new EffectControlType(typeof(ShadowEffectControl)));
            listEffectControlTypes.Add(new EffectControlType(typeof(SepiaEffectControl)));
            listEffectControlTypes.Add(new EffectControlType(typeof(ScaleEffectControl)));
            listEffectControlTypes.Add(new EffectControlType(typeof(ColorReplacementEffectControl)));

            listEffectControlTypes.Add(new EffectControlType(typeof(BrightnessToTransparencyEffectControl)));
            listEffectControlTypes.Add(new EffectControlType(typeof(ClearTransparencyEffectControl)));
            listEffectControlTypes.Add(new EffectControlType(typeof(DissolveEffectControl)));
            listEffectControlTypes.Add(new EffectControlType(typeof(BlackOrWhiteEffectControl)));
            listEffectControlTypes.Add(new EffectControlType(typeof(HighLightRevealEffectControl)));
            listEffectControlTypes.Add(new EffectControlType(typeof(DistortionEffectControl)));
            listEffectControlTypes.Add(new EffectControlType(typeof(WaveEffectControl)));
            listEffectControlTypes.Add(new EffectControlType(typeof(WaveRippleEffectControl)));
            listEffectControlTypes.Add(new EffectControlType(typeof(SwellOrExtrusionEffectControl)));
            listEffectControlTypes.Add(new EffectControlType(typeof(ColorFadeEffectContrl)));
            

            #region
            listCalute.Add(new EffectControlType(typeof(FrameControl)));
            listCalute.Add(new EffectControlType(typeof(TextBoxSlider)));
            listCalute.Add(new EffectControlType(typeof(AddControl)));
            listCalute.Add(new EffectControlType(typeof(SubControl)));
            listCalute.Add(new EffectControlType(typeof(MultiplyControl)));
            listCalute.Add(new EffectControlType(typeof(Vector2Control)));
            listCalute.Add(new EffectControlType(typeof(Vector4Control)));
            
            #endregion

            listEffectControlTypes = listEffectControlTypes.OrderBy((a) => { return a.Category; }).ToList();
            this.cvs.Source = listEffectControlTypes.GroupBy((p) => { return p.Category; });



            displayEffect.ConnectSource += Ec_ConnectSource;
            displayEffect.ConnectSourceChanged += Ec_ConnectSourceChanged;
            //var obj = Activator.CreateInstance(ect.Type);
        }

        #region 面板拖动
        private void connentPanel_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
        {
            Window.Current.CoreWindow.PointerCursor = new Windows.UI.Core.CoreCursor(Windows.UI.Core.CoreCursorType.Arrow, 1);
        }

        private void connentPanel_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
        {
            var element = e.Container;
            if (e.OriginalSource != connentPanel)
                return;
            Window.Current.CoreWindow.PointerCursor = new Windows.UI.Core.CoreCursor(Windows.UI.Core.CoreCursorType.Hand, 1);

            foreach (var item in connentPanel.Children)
            {
                if (item is EffectContentControl control)
                {
                    var point = new Point(control.ControlPoint.X + e.Delta.Translation.X, control.ControlPoint.Y + e.Delta.Translation.Y);
                    control.ControlPoint = point;
                    SetEffectControlPosition(control);
                }

                //item.Translation = new Vector3((float)(item.Translation.X + e.Delta.Translation.X), (float)(item.Translation.Y + e.Delta.Translation.Y), 0);
            }

            foreach (var item in listConnectLines)
            {
                item.DrawConnectLine();
            }


        }
        #endregion



        #region 效果控件拖动

        /// <summary>
        /// 拖动完成
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void EffectContentControl_HeaderDeltaCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
        {

        }

        /// <summary>
        /// 控件拖动
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void EffectContentControl_HeaderDelta(object sender, ManipulationDeltaRoutedEventArgs e)
        {
            if (sender is EffectContentControl control)
            {
                SetSelectEffectControl(sender);

                var point = new Point(control.ControlPoint.X + e.Delta.Translation.X, control.ControlPoint.Y + e.Delta.Translation.Y);
                control.ControlPoint = point;
                SetEffectControlPosition(control);
                //当前是输出控件
                if (control.Content is ProviderDataControl effectControl)
                {
                    //获取所有输出连接元素
                    var outputConnect = effectControl.GetConnectLineAll();
                    foreach (var item in outputConnect)
                    {
                        var connectLine = listConnectLines.Single((p) => { return p.ConnectElement == item; });
                        if (connectLine != null)
                        {
                            connectLine.DrawConnectLine();
                        }
                    }
                }
            }
        }
        #endregion

        /// <summary>
        /// 设置效果控件位置
        /// </summary>
        /// <param name="control"></param>
        private void SetEffectControlPosition(EffectContentControl control)
        {
            Canvas.SetLeft(control, control.ControlPoint.X);
            Canvas.SetTop(control, control.ControlPoint.Y);
        }

        #region 事件

        /// <summary>
        /// 删除所有连接该效果控件的线
        /// </summary>
        /// <param name="allConnectElement"></param>
        private void Ec_DeleteAllConnnect(IExporter control, List<ConnectLineUIElement> allConnectElement)
        {
            foreach (var item in allConnectElement)
            {
                var connectLine = listConnectLines.Single((p) => { return p.ConnectElement == item; });
                if (connectLine != null)
                {
                    connentPanel.Children.Remove(connectLine);
                    listConnectLines.Remove(connectLine);
                }
            }

            allConnectElement.Clear();
            allConnectElement = null;
        }

        /// <summary>
        /// 删除效果控件按钮事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        /// <exception cref="NotImplementedException"></exception>
        private void ContentControl_DeleteClick(object sender, RoutedEventArgs e)
        {
            if (sender is EffectContentControl effectContent)
            {
                connentPanel.Children.Remove(effectContent);
            }
        }

        /// <summary>
        /// 更改连接源头
        /// </summary>
        /// <param name="newSourceUIElement"></param>
        /// <param name="oldSourceUIElement"></param>
        /// <param name="targetUIelement"></param>
        private void Ec_ConnectSourceChanged(ConnectLineUIElement newConnectElement, ConnectLineUIElement oldConnectElement)
        {
            var connectLine = listConnectLines.Single((p) => { return p.ConnectElement == oldConnectElement; });
            if (connectLine != null)
            {
                connectLine.SetConnectElement(newConnectElement);
            }
        }

        /// <summary>
        /// 连接源头
        /// </summary>
        /// <param name="sourceUIElement"></param>
        /// <param name="targetUIElement"></param>
        private void Ec_ConnectSource(ConnectLineUIElement connectElement)
        {
            //创建连接的线段
            ConnectLine connectLine = new ConnectLine(connectElement, connentPanel);
            connectLine.DoubleTapped += ConnectLine_DoubleTapped;
            //添加到界面中
            connentPanel.Children.Insert(0, connectLine);
            //添加到线段连接列表中
            listConnectLines.Add(connectLine);

        }

        /// <summary>
        /// 双击连接的线段，断开连接
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        /// <exception cref="NotImplementedException"></exception>
        private void ConnectLine_DoubleTapped(object sender, DoubleTappedRoutedEventArgs e)
        {
            if (sender is ConnectLine connectLine)
            {
                //断开连接
                connectLine.ConnectElement.Exporter.Disconnect(connectLine.ConnectElement);
                connentPanel.Children.Remove(connectLine);
                listConnectLines.Remove(connectLine);
            }
        }

        #endregion


        /// <summary>
        /// 初始化效果控件的位置和事件
        /// </summary>
        /// <param name="contentControl"></param>
        private void InitialEffectContentControl(ProviderDataControl control)
        {

            EffectContentControl contentControl = new EffectContentControl();

            contentControl.Content = control;


            var w = connentPanel.ActualWidth;
            var h = connentPanel.ActualHeight;
            Point cp = new Point(w / 2, h / 2);
            contentControl.ControlPoint = cp;

            connentPanel.Children.Add(contentControl);
            SetEffectControlPosition(contentControl);


            control.ConnectSource += Ec_ConnectSource;
            control.ConnectSourceChanged += Ec_ConnectSourceChanged;
            control.DeleteAllConnnect += Ec_DeleteAllConnnect;
            zIndex++;
Canvas.SetZIndex(contentControl, zIndex);

            contentControl.HeaderDelta += EffectContentControl_HeaderDelta;
            contentControl.HeaderDeltaCompleted += EffectContentControl_HeaderDeltaCompleted;
            contentControl.DeleteClick += ContentControl_DeleteClick;
            contentControl.Tapped += ContentControl_Tapped;


        }

        private void ListView_ItemClick(object sender, ItemClickEventArgs e)
        {
            var item = (EffectControlType)e.ClickedItem;
            if (item != null)
            {
                var control = Activator.CreateInstance(item.Type);
                if (control is ProviderDataControl cl)
                {
                    InitialEffectContentControl(cl);
                }
              
            }
        }

        /// <summary>
        /// 效果拖动外壳点击事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ContentControl_Tapped(object sender, TappedRoutedEventArgs e)
        {
            SetSelectEffectControl(sender);
        }

        /// <summary>
        /// 设置当前选中项
        /// </summary>
        /// <param name="sender"></param>
        private void SetSelectEffectControl(object sender)
        {
            if (sender is EffectContentControl ecc)
            {
                if (selectEffectContentControl != ecc)
                {
                    selectEffectContentControl = ecc;
                    zIndex++;
                    Canvas.SetZIndex(selectEffectContentControl, zIndex);
                }
            }
        }
    }

    public class EffectControlType
    {
        public EffectControlType(Type type)
        {
            this.Type = type;
            this.Name = Type.Name.Replace("Control", "");
            this.Content = $"添加{Name}控件";
            this.Category = Name.Substring(0, 1);
        }

        public Type Type { get; set; }

        public string Name { get; set; }

        public string Content { get; set; }

        public string Category { get; set; }

    }
}
